package jblip.gui.components.view;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Observable;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import jblip.gui.JBlip;
import jblip.gui.data.channels.UpdatesDataChannel;
import jblip.gui.data.channels.UserDataChannel;
import jblip.gui.data.images.ImageCache;
import jblip.gui.data.images.ImageChangeListener;
import jblip.resources.Media;
import jblip.resources.Update;

public class UpdateChannelPanel extends ChannelViewPanel<Update> implements
    ImageChangeListener {
  private static int INITIAL_SIZE = 15;

  private final JPanel updates_panel;

  public UpdateChannelPanel(final UpdatesDataChannel channel) {
    super(channel);

    final BoxLayout layout = new BoxLayout(this, BoxLayout.X_AXIS);
    this.setLayout(layout);

    updates_panel = new JPanel();
    updates_panel.setOpaque(false);
    updates_panel.setLayout(new BoxLayout(updates_panel, BoxLayout.Y_AXIS));
    for (int i = 0; i < INITIAL_SIZE && i < channel.size(); i++) {
      final int idx = channel.size() - 1 - i; // read from the back
      updates_panel.add(new UpdateComponent(channel.get(idx)));
      updates_panel.add(Box.createVerticalStrut(5));
    }

    this.add(Box.createHorizontalGlue());
    this.add(updates_panel);
    this.add(Box.createHorizontalGlue());

    if (channel instanceof UserDataChannel) {
      // load background
      final String uname = ((UserDataChannel) channel).getUserName();
      final ImageCache cache = JBlip.instance().getImageCache();
      final Media bg = JBlip.instance().getBlipClient().getBackground(uname);
      if (bg != null) {
        try {
          cache.getImage(new URL(bg.getURL()), this);
        } catch (MalformedURLException e) {
          // Blip API gave us wrong URL?
          e.printStackTrace();
        }
      }
    }

    this.repaint();
  }

  private static final long serialVersionUID = 1L;

  @Override
  public void update(final Observable o, final Object arg) {
    synchronized (this) {
      // wait until constructor finishes
      try {
        while (updates_panel == null) {
          wait(50);
        }
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }

    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        if (arg instanceof Iterable<?>) {
          int i = 0;
          for (Object obj : (Iterable<?>) arg) {
            final Update up = (Update) obj;
            updates_panel.add(new UpdateComponent(up), i++);
            updates_panel.add(Box.createVerticalStrut(5), i++);
          }
          updates_panel.repaint();
          UpdateChannelPanel.this.setSize(getPreferredSize());
        }
      }
    });
  }

  @Override
  public synchronized void imageChange(final Image bg) {
    this.bgimage = bg;
    invalidate();
    repaint();
  }

  @Override
  protected void paintComponent(final Graphics g) {
    // paint background, then component
    synchronized (this) {
      if (bgimage != null && bgimage.getWidth(this) != -1
          && bgimage.getHeight(this) != -1 && isShowing()) {
        final Rectangle screen = getVisibleRect();
        int next_w = 0;
        int next_h = 0;
        while (next_h < screen.height) {
          g.drawImage(bgimage, screen.x + next_w, screen.y + next_h, this);
          next_w += bgimage.getWidth(this);
          if (next_w > screen.width) {
            next_h += bgimage.getHeight(this);
            next_w = 0;
          }
        }
      }
    }

    super.paintComponent(g);
  }
}
